import numpy as np
import cv2
import matplotlib.pyplot as plt
import os

# 读取图片
img = cv2.imread('hanzi.png')

# 转换为灰度图
gray_img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

# 进行二值处理
_ ,binary = cv2.threshold(gray_img,0 ,255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)

# 将白色背景转变为黑色
inverted_binary = cv2.bitwise_not(binary)

# 应用腐蚀操作去除噪点
kernel = np.ones((3,3),np.uint8)
eroded = cv2.erode(inverted_binary, kernel, iterations=4)

# 应用膨胀突出图像特征
dilated = cv2.dilate(eroded, kernel, iterations=6)

# 中值滤波
median = cv2.medianBlur(dilated, 5)

# 闭运算
closed = cv2.morphologyEx(median, cv2.MORPH_CLOSE, kernel,iterations = 30)

# Canney边缘识别
edges = cv2.Canny(closed, 100, 200)

# 提取轮廓
contours, _ = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

# 复制图像以绘制边界框
img_copy = img.copy()

# 遍历轮廓列表
for c in contours:
    perimeter = cv2.arcLength(c, True)
    print("轮廓周长：", perimeter)

    x, y, w, h = cv2.boundingRect(c)
    cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)

    # 根据周长阈值筛选并绘制边界框
    if perimeter > 100:
        cv2.rectangle(img_copy, (x, y), (x + w, y + h), (0, 255, 0), 2)



contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# 创建保存汉字图片的文件夹
save_dir = 'chars'
os.makedirs(save_dir, exist_ok=True)

# 为每个轮廓创建并保存图像
index = 1  # 初始化序号
for c in contours:
    # 计算轮廓的边界框
    x, y, w, h = cv2.boundingRect(c)
    
    # 检查轮廓的面积是否足够大，以忽略小的噪点
    if w * h > 100:  # 面积阈值可以根据实际情况调整
        # 截取汉字区域
        char_img = img[y:y+h, x:x+w]
        
        # 保存汉字图像
        save_path = os.path.join(save_dir, f'char_{index:03d}.png')
        cv2.imwrite(save_path, char_img)
        
        # 更新序号
        index += 1
        

# 设置matplotlib支持中文的字体
plt.rcParams['font.sans-serif'] = ['SimHei']  # 指定默认字体为黑体
plt.rcParams['axes.unicode_minus'] = False

# 绘制图像
fig, axs = plt.subplots(1, 8,figsize =(24,3))

axs[2].imshow(eroded, cmap='gray')
axs[2].set_title('侵蚀后的图像')

axs[0].imshow(gray_img, cmap='gray')
axs[0].set_title('灰度图像')

axs[1].imshow(inverted_binary, cmap='gray')
axs[1].set_title('二值化图像')

axs[4].imshow(median, cmap='gray')
axs[4].set_title('中值滤波图像')

axs[3].imshow(dilated, cmap='gray')
axs[3].set_title('膨胀后的图像')

axs[5].imshow(closed, cmap='gray')
axs[5].set_title('闭运算后的图像')

axs[6].imshow(edges, cmap='gray')
axs[6].set_title('边缘检测图像')

axs[7].imshow(img_copy)
axs[7].set_title('结果图像')


# 显示图像
plt.tight_layout()
plt.show()